<?php
/**
 * Created by PhpStorm.
 * User: 1
 * Date: 2017-08-04
 * Time: 14:10
 */

namespace app\index\command;


use app\index\helper\CommandHelper;
use sunsun\decoder\SunsunTDS;
use think\console\Command;
use think\console\Input;
use think\console\input\Option;
use think\console\Output;
use think\Exception;

class TcpClientCommand extends Command
{
    protected $portClient = [
        '8286'=>[],
        '8283'=>[]
    ];
    protected function initialize(Input $input, Output $output)
    {
        CommandHelper::loadLang(['zh-cn', 'en', 'zh-tw']);
    }

    protected function configure()
    {
        $this->setName('tcp:test')
            ->addOption('start','',Option::VALUE_OPTIONAL,'tcp client start index',0)
            ->addOption('size','',Option::VALUE_OPTIONAL,'tcp client size,total size in 8286.txt',1)
            ->addOption('times','',Option::VALUE_OPTIONAL,'heart beat times (3 per seconds)',20)
            ->addOption('port','',Option::VALUE_OPTIONAL,'tcp client test port(water_pump = 8286,heating_rod = 8283)',8286)
            ->setDescription('tcp test process');
    }

    protected function execute(Input $input, Output $output)
    {
        $this->initData($output);
        $address = '101.37.37.167';
        $publicPwd = '1234bcda';
        $time = microtime(true);
        $start = $input->getOption('start');
        $size = $input->getOption('size');
        $port = $input->getOption('port');
        $times = $input->getOption('times');
        $output->info('start '.$size.' tcp socket from '.$start);
        $portClients = $this->portClient;
        $sockets = [];
        $clients = $portClients[$port];
        if(count($clients) < $size){
            $output->info('option size can\'t bigger than clients size');
            return ;
        }

        $total = count($clients);
        for($i=0;$i<$size;$i++){
            $socket = stream_socket_client('tcp://'.$address.':'.$port,$errno, $errstr, 30);
            array_push($sockets,$socket);//$this->createSocketClient($address,$port));
//            sleep(1);
            $one  = $clients[$i+$start];
            $sock = $socket;
            $type = $one['type'];
//            $output->info('login ctrl_pwd='.$one['ctrl_pwd'].'  pwd='.$one['pwd']);
            $pwd  = SunsunTDS::encodePwd($one['ctrl_pwd'], $one['pwd']);
            $entity = [
                'reqType'=>$type,
                'sn'=>rand(10000,99999),
                'did'=>$one['did'],
                'ver'=>'V1.0',
                'pwd'=>base64_decode($pwd)
            ];
            $sendData = SunsunTDS::encode($entity, $publicPwd);
//            $output->info('login did='.$one['did']);
                fwrite($sock,$sendData);
//            $result = socket_connect($sock, $address, $port);
//            $result = socket_connect($sock, $address, $port);
//            if ($result < 0) {
//                echo "SOCKET连接失败原因: ($result) " . socket_strerror($result) . "\n";
//            } else {
//                echo "OK.\n";
//                socket_write($sock, $sendData);
//            }
        }

        // 保持心跳请求 40次 20分钟左右
        $cnt = 1;
        while(true){
            $output->info('heart beat '.$cnt. ' times');
            for($i=0;$i<$size;$i++){
                $one  = $clients[$i + $start];
                $sock = $sockets[$i];
                $type = $one['hbType'];
                $entity = [
                    'reqType'=>$type,
                    'sn'=>rand(10000,99999)
                ];
                $sendData = SunsunTDS::encode($entity, $one['pwd']);
                try{
                    fwrite($sock, $sendData);
                }catch (\Exception $ex){
                    $output->error($ex->getMessage());
                }

            }
            sleep(60);
            $cnt++;
            if($cnt > $times){
                break;
            }
        }

        sleep(5);
        for($i=0;$i<$size;$i++){
            fclose($sockets[$i]);
        }

        $cost_time = microtime(true) - $time;
        $output->info('cost '.$cost_time.' s');
    }

    protected function initData(Output $output)
    {

        foreach ($this->portClient as $key => &$value) {
            $fileName = ($key . '.txt');
            if (file_exists($fileName)) {
                $f = fopen($fileName, "r");
                $cnt = 0;
                $hbType = '';
                $type = '';
                $pwd = '';
                while (!feof($f)) {
                    $line = fgets($f);
                    $lineData = explode(' ', $line);
                    if ($cnt == 0) {
                        $hbType = $lineData[0];
                        $type = $lineData[1];
                        $pwd = $lineData[2];
                    } else {
                        $data = [
                            'did' => $lineData[0],
                            'pwd' => $lineData[1],
                            'ctrl_pwd' => $pwd,
                            'hbType' => $hbType,
                            'type' => $type
                        ];
                        array_push($value, $data);
                    }
                    $cnt++;
                }
                fclose($f);
            } else {
                $output->info($fileName . ' not exist');
            }
        }
//        var_dump($this->portClient);
    }
}